package com.tencent.wxpay.protocol.request;

import com.tencent.wxpay.common.Signature;
import com.tencent.wxpay.protocol.model.FeeType;
import com.tencent.wxpay.protocol.model.TradeType;

import java.io.Serializable;

/**
 * 统一下单接口请求数据对象
 */
public class UnifiedOrderReqData extends BaseReqData implements Serializable {

    private static final long serialVersionUID = 7404845312172352450L;
    /**
     * 设备号
     * 必填：否
     * 描述：终端设备号(门店号或收银设备ID)，注意：PC网页或公众号内支付请传"WEB"
     */
    private String device_info;

    /**
     * 商品描述
     * 必填：是
     * 描述：商品简单描述，该字段须严格按照规范传递，具体请见<a href="https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_2">参数规定</a>
     */
    private String body;
    /**
     * 商品详情
     * 必填：否
     * 描述：商品详细列表，使用Json格式，传输签名前请务必使用CDATA标签将JSON文本串保护起来。
     * goods_detail []：
     * └ goods_id String 必填 32 商品的编号
     * └ wxpay_goods_id String 可选 32 微信支付定义的统一商品编号
     * └ goods_name String 必填 256 商品名称
     * └ quantity Int 必填 商品数量
     * └ price Int 必填 商品单价，单位为分
     * └ goods_category String 可选 32 商品类目ID
     * └ body String 可选 1000 商品描述信息
     */
    private String detail;
    /**
     * 附加数据
     * 必填：否
     * 描述：附加数据，在查询API和支付通知中原样返回，该字段主要用于商户携带订单的自定义数据
     */
    private String attach;
    /**
     * 商户订单号
     * 必填：是
     * 描述：商户系统内部的订单号,32个字符内、可包含字母, 其他说明见<a href="https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_2">商户订单号</a>
     */
    private String out_trade_no;
    /**
     * 货币类型
     * 必填：否
     * 描述：符合ISO 4217标准的三位字母代码，默认人民币：CNY，其他值列表详见<a href="https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_2">货币类型</a>
     */
    private String fee_type;
    /**
     * 总金额
     * 必填：是
     * 描述：订单总金额，单位为分，详见<a href="https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_2">支付金额</a>
     */
    private int total_fee;
    /**
     * 终端IP
     * 必填：是
     * 描述：APP和网页支付提交用户端ip，Native支付填调用微信支付API的机器IP。
     */
    private String spbill_create_ip;
    /**
     * 交易起始时间
     * 必填：否
     * 描述：订单生成时间，格式为yyyyMMddHHmmss，如2009年12月25日9点10分10秒表示为20091225091010。其他详见<a href="https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_2">时间规则</a>
     */
    private String time_start;
    /**
     * 交易结束时间
     * 必填：否
     * 描述：订单失效时间，格式为yyyyMMddHHmmss，如2009年12月27日9点10分10秒表示为20091227091010。其他详见<a href="https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_2">时间规则</a>
     * 注意：最短失效时间间隔必须大于5分钟
     */
    private String time_expire;
    /**
     * 商品标记
     * 必填：否
     * 描述：商品标记，代金券或立减优惠功能的参数，说明详见<a href="https://pay.weixin.qq.com/wiki/doc/api/tools/sp_coupon.php?chapter=12_1">代金券或立减优惠</a>
     */
    private String goods_tag;
    /**
     * 通知地址
     * 必填：是
     * 描述：接收微信支付异步通知回调地址，通知url必须为直接可访问的url，不能携带参数。
     */
    private String notify_url;
    /**
     * 交易类型
     * 必填：是
     * 描述：取值如下：JSAPI，NATIVE，APP，详细说明见<a href="https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_2">参数规定</a>
     */
    private String trade_type;
    /**
     * 商品ID
     * 必填：否
     * 描述：trade_type=NATIVE，此参数必传。此id为二维码中包含的商品ID，商户自行定义。
     */
    private String product_id;
    /**
     * 指定支付方式
     * 必填：否
     * 描述：no_credit--指定不能使用信用卡支付
     */
    private String limit_pay;
    /**
     * 用户标识
     * 必填：否
     * 描述：trade_type=JSAPI，此参数必传，用户在商户appid下的唯一标识。openid如何获取，可参考【<a href="https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_4">获取openid</a>】。企业号请使用【<a href="http://qydev.weixin.qq.com/wiki/index.php?title=OAuth%E9%AA%8C%E8%AF%81%E6%8E%A5%E5%8F%A3">企业号OAuth2.0接口</a>】获取企业号内成员userid，再调用【<a href="http://qydev.weixin.qq.com/wiki/index.php?title=Userid%E4%B8%8Eopenid%E4%BA%92%E6%8D%A2%E6%8E%A5%E5%8F%A3">企业号userid转openid接口</a>】进行转换
     */
    private String openid;

    /**
     * 交易类型为JSAPI时统一下单接口的构造方法(所有必填项)
     *
     * @param body           要支付的商品的描述信息，用户会在支付成功页面里看到这个信息,该字段须严格按照规范传递
     * @param outTradeNo     商户系统内部的订单号,32个字符内,可包含字母, 确保在商户系统唯一
     * @param totalFee       订单总金额，单位为“分”，只能整数
     * @param spBillCreateIP 终端IP
     * @param notifyUrl      接收微信支付异步通知回调地址，通知url必须为直接可访问的url，不能携带参数。
     * @param tradeType      交易类型 取值如下：JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付
     * @param productId      trade_type=NATIVE，此参数必传，此id为二维码中包含的商品ID，商户自行定义。
     * @param openid         trade_type=JSAPI，此参数必传，用户在商户appid下的唯一标识。
     */
    public UnifiedOrderReqData(String body, String outTradeNo, int totalFee, String spBillCreateIP, String notifyUrl, TradeType tradeType, String productId, String openid) {
        super();
        this.body = body;
        this.out_trade_no = outTradeNo;
        this.total_fee = totalFee;
        this.spbill_create_ip = spBillCreateIP;
        this.notify_url = notifyUrl;
        this.trade_type = tradeType.toString();
        this.product_id = productId;
        this.openid = openid;
        setSign(Signature.getSign(toMap(this)));//把签名数据设置到Sign这个属性中
    }

    /**
     * 统一下单接口的构造方法(所有必填项，再加上订单的生成失效日期)
     *
     * @param body           要支付的商品的描述信息，用户会在支付成功页面里看到这个信息,该字段须严格按照规范传递
     * @param outTradeNo     商户系统内部的订单号,32个字符内,可包含字母, 确保在商户系统唯一
     * @param totalFee       订单总金额，单位为“分”，只能整数
     * @param spBillCreateIP 终端IP
     * @param timeStart      订单生成时间，格式为yyyyMMddHHmmss，如2009年12月25日9点10分10秒表示为20091225091010。
     * @param timeExpire     订单失效时间，格式同上
     * @param notifyUrl      接收微信支付异步通知回调地址，通知url必须为直接可访问的url，不能携带参数。
     * @param tradeType      交易类型 取值如下：JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付
     * @param productId      trade_type=NATIVE，此参数必传，此id为二维码中包含的商品ID，商户自行定义。
     * @param openid         trade_type=JSAPI，此参数必传，用户在商户appid下的唯一标识。
     */
    public UnifiedOrderReqData(String body, String outTradeNo, int totalFee, String spBillCreateIP, String timeStart, String timeExpire, String notifyUrl, TradeType tradeType, String productId, String openid) {
        super();
        this.body = body;
        this.out_trade_no = outTradeNo;
        this.total_fee = totalFee;
        this.spbill_create_ip = spBillCreateIP;
        this.time_start = timeStart;
        this.time_expire = timeExpire;
        this.notify_url = notifyUrl;
        this.trade_type = tradeType.toString();
        this.product_id = productId;
        this.openid = openid;
        setSign(Signature.getSign(toMap(this)));//把签名数据设置到Sign这个属性中
    }

    /**
     * 统一下单接口的构造方法(所有项，包括非必填项)
     *
     * @param body           要支付的商品的描述信息，用户会在支付成功页面里看到这个信息,该字段须严格按照规范传递
     * @param detail         商品详情,商品详细列表，使用Json格式，传输签名前请务必使用CDATA标签将JSON文本串保护起来。
     * @param attach         附加数据，在查询API和支付通知中原样返回，该字段主要用于商户携带订单的自定义数据
     * @param outTradeNo     商户系统内部的订单号,32个字符内,可包含字母, 确保在商户系统唯一
     * @param feeType        货币类型,默认人民币：CNY
     * @param totalFee       订单总金额，单位为“分”，只能整数
     * @param spBillCreateIP 终端IP
     * @param timeStart      订单生成时间，格式为yyyyMMddHHmmss，如2009年12月25日9点10分10秒表示为20091225091010。
     * @param timeExpire     订单失效时间，格式同上
     * @param goodsTag       商品标记，代金券或立减优惠功能的参数
     * @param notifyUrl      接收微信支付异步通知回调地址，通知url必须为直接可访问的url，不能携带参数。
     * @param tradeType      交易类型 取值如下：JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付
     * @param productId      trade_type=NATIVE，此参数必传，此id为二维码中包含的商品ID，商户自行定义。
     * @param limitPay       指定支付方式 no_credit--指定不能使用信用卡支付
     * @param openid         trade_type=JSAPI，此参数必传，用户在商户appid下的唯一标识。
     */
    public UnifiedOrderReqData(String body, String detail, String attach, String outTradeNo, FeeType feeType, int totalFee, String spBillCreateIP, String timeStart, String timeExpire, String goodsTag, String notifyUrl, TradeType tradeType, String productId, String limitPay, String openid) {
        super();
        this.body = body;
        this.detail = detail;
        this.attach = attach;
        this.out_trade_no = outTradeNo;
        this.fee_type = feeType.toString();
        this.total_fee = totalFee;
        this.spbill_create_ip = spBillCreateIP;
        this.time_start = timeStart;
        this.time_expire = timeExpire;
        this.goods_tag = goodsTag;
        this.notify_url = notifyUrl;
        this.trade_type = tradeType.toString();
        this.product_id = productId;
        this.limit_pay = limitPay;
        this.openid = openid;
        setSign(Signature.getSign(toMap(this)));//把签名数据设置到Sign这个属性中
    }

    public String getDevice_info() {
        return device_info;
    }

    public void setDevice_info(String device_info) {
        this.device_info = device_info;
    }

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }

    public String getDetail() {
        return detail;
    }

    public void setDetail(String detail) {
        this.detail = detail;
    }

    public String getAttach() {
        return attach;
    }

    public void setAttach(String attach) {
        this.attach = attach;
    }

    public String getOut_trade_no() {
        return out_trade_no;
    }

    public void setOut_trade_no(String out_trade_no) {
        this.out_trade_no = out_trade_no;
    }

    public String getFee_type() {
        return fee_type;
    }

    public void setFee_type(FeeType fee_type) {
        this.fee_type = fee_type.toString();
    }

    public int getTotal_fee() {
        return total_fee;
    }

    public void setTotal_fee(int total_fee) {
        this.total_fee = total_fee;
    }

    public String getSpbill_create_ip() {
        return spbill_create_ip;
    }

    public void setSpbill_create_ip(String spbill_create_ip) {
        this.spbill_create_ip = spbill_create_ip;
    }

    public String getTime_start() {
        return time_start;
    }

    public void setTime_start(String time_start) {
        this.time_start = time_start;
    }

    public String getTime_expire() {
        return time_expire;
    }

    public void setTime_expire(String time_expire) {
        this.time_expire = time_expire;
    }

    public String getGoods_tag() {
        return goods_tag;
    }

    public void setGoods_tag(String goods_tag) {
        this.goods_tag = goods_tag;
    }

    public String getNotify_url() {
        return notify_url;
    }

    public void setNotify_url(String notify_url) {
        this.notify_url = notify_url;
    }

    public String getTrade_type() {
        return trade_type;
    }

    public void setTrade_type(TradeType trade_type) {
        this.trade_type = trade_type.toString();
    }

    public String getProduct_id() {
        return product_id;
    }

    public void setProduct_id(String product_id) {
        this.product_id = product_id;
    }

    public String getLimit_pay() {
        return limit_pay;
    }

    public void setLimit_pay(String limit_pay) {
        this.limit_pay = limit_pay;
    }

    public String getOpenid() {
        return openid;
    }

    public void setOpenid(String openid) {
        this.openid = openid;
    }
}
